package com.office.office.wps;

import com.office.config.BuilderConfigInfo;
import com.office.config.wps.*;
import com.office.core.*;
import com.office.core.context.FileMetadata;
import com.office.office.wps.dto.FileConvertResult;
import com.office.office.wps.dto.OnnotifyMessage;
import com.office.office.wps.dto.TaskQueryResult;
import com.office.tools.wps.PreviewMode;
import com.office.tools.wps.SDKUtil;
import com.office.tools.wps.UserPermission;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Map;

/*
 * @BelongsProject: office
 * @BelongsPackage: com.office.office.wps
 * @Author: TongHui
 * @CreateTime: 2024-03-13 11:02
 * @Description: TODO
 * @Version: 1.0
 */
@Data
public abstract class AbstractWPSOfficeBase {

    private static final Logger log = LoggerFactory.getLogger(AbstractWPSOfficeBase.class);

    /**
     * 公共的配置信息
     */
    protected final CommonConfig configuration;
    /**
     * 本地缓存
     */
    protected Cache cache;
    /**
     * 回调处理
     */
    protected MessageHandle messageHandle;
    /**
     * wps专属配置
     */
    protected WPSBaseInfo wpsBaseInfo;

    /**
     * wps中台接口
     */
    protected SDKUtil sdkUtil;
    protected String EDIT = "edit";
    protected String VIEW = "view";

    public AbstractWPSOfficeBase(CommonConfig configuration) {
        this.configuration = configuration;
    }


    /**
     * @return 服务名称
     */
    protected String getServerName() {
        return "wps-";
    }



    /**
     * 获取文件下载路径
     * @param fileId  文件id
     * @return 下载路径
     */
    public String getDownlaodUrl(String fileId){
        if (configuration.getDowloadFile().endsWith("/")) {
            return configuration.getDowloadFile() + fileId ;
        }
        return configuration.getDowloadFile() + "/"+ fileId;
    }

    /**
     * 缓存数据
     * @param key   键
     * @param value 值
     */
    public void setCache(String key, String value) {
        cache.set(key, value);
    }

    /**
     * 获取规定历史文件数量
     * @return 历史文件数量
     */
    public Integer getHistNum() {
        return configuration.getHistNum();
    }


    /**
     * 设置文件元数据
     * @param map{
     *           必填 fileId
     *           必填 fileName
     *           必填 fileType
     *           必填 fileSize
     *           可用携带其它值
     * }
     * @return 文件元数据
     * @throws Exception 返回异常
     */
    protected FileMetadata handlerFile(Map<String, Object> map) throws Exception {
        try {
            String id = (String) map.get("fileId");
            //  生成临时可访问文件的url
            String tempUrl = getDownlaodUrl(id);

            return  FileMetadata.builder()
                    // 可访问路径
                    .url(tempUrl)
                    // 原来的文件名
                    .oldName((String) map.get("fileName"))
                    .fileType((String) map.get("fileType"))
                    .fileInfo(map)
                    // 唯一标识
                    .key(id)
                    .openTime(new Date().getTime())
                    .build();
        } catch (Exception e) {
            log.error("生成临时文件失败", e);
            throw e;
        }
    }


    /**
     * 校验自定义参数
     */

    protected void verifyCustomParameter(Map<String,String> params){
        if(params == null){
            return;
        }
        if (params.containsKey(ConstantsWPS.APPID)){
            throw new IllegalArgumentException("参数冲突："+ConstantsWPS.APPID+"该参数名已被使用");
        }
        if (params.containsKey(ConstantsWPS.FILEID)){
            throw new IllegalArgumentException("参数冲突："+ConstantsWPS.FILEID+"该参数名已被使用");
        }
    }


    /**
     *  获取打开文件的连接
     * @param fileId  文件id
     * @param fileName  文件名称
     * @param _w_tokentype 是否传token
     * @param params       自定义参数
     *  @return  link
     */
    public abstract String openDocument(String fileId, String fileName, Integer _w_tokentype,Map<String,String> params);


    /**
     *
     * @param fileId  文件id
     * @param fileName  文件名称
     * @param _w_tokentype 是否传token
     * @param previewMode 预览类型
     * @param wpsPreview 高清预览支持控制修订痕迹、评论是否显示等参数。 览参数wpsPreview=1111111从左到右依次代表：
     *                   第0位：格式修订：0不显示；1：显示
     *                   第1位：插入和删除：0不显示；1：显示
     *                   第2位：评论 0不显示；1：显示
     *                   第3位：以嵌入模式显示修订
     *                   第4位：以气泡模式显示修订
     *                   第5位：0不显示标记；1：显示标记
     *                   第6位：0最终状态；1：原始状态
     *       注：(第3、4位组合：01及11为批注框方式；10是嵌入方式
     *       00是批注框显示修订者)
     * @param params 自定义参数
     *  @return  link
     */
    public abstract String openDocument(String fileId, String fileName,PreviewMode previewMode, Integer _w_tokentype,String  wpsPreview, Map<String,String> params);


    /**
     * 生成wps 所需配置信息
     * @param fileMeta   文件元数据
     * @param fileInfo   文件信息
     * @param userInfo   用户信息
     * @return  配置信息
     */
    public Map<String,Object> generateConfig(Map<String, Object> fileMeta, FileInfo fileInfo, UserInfo userInfo) {
        return generateConfig(fileMeta, fileInfo,null, null,userInfo);
    }
    /**
     * 生成wps 所需配置信息
     * @param fileMeta   文件元数据
     * @param fileInfo   文件信息
     * @param userAcl    用户权限信息
     * @param watermark  水印信息
     * @param userInfo   用户信息
     * @return  配置信息
     */
    public Map<String,Object> generateConfig(Map<String, Object> fileMeta, FileInfo fileInfo, UserAcl userAcl, FileWatermark watermark, UserInfo userInfo) {
        try {
            //校验用户权限是否为 read
            if (UserPermission.read.equals(userInfo.getPermission())){
                Integer preview_pages = fileInfo.getPreview_pages();
                if (preview_pages == null){
                    fileInfo.setPreview_pages(0);
                }
            }
            //校验水印类型
            if (null != watermark && watermark.getType() == ConstantsWPS.WATERMARK_TYPE_Y){
                if (StringUtils.isEmpty(watermark.getValue())){
                    throw new IllegalStateException("watermark.value: is null");
                }
            }

            log.info("开始生成文件信息");
            //在编辑模式 生成临时文件，保存原文件信息
            FileMetadata tempFileInfo = handlerFile(fileMeta);
            //生成配置文件 TODO: 控制文件权限
            log.info("开始生成编辑器配置信息");
            fileInfo.setDownload_url(tempFileInfo.getUrl());

            Map<String,Object> config = BuilderConfigInfo.builderWpsConfig(fileInfo, userAcl, watermark, userInfo);
            log.info("生成编辑器配置信息结束");
            // TODO: 添加更多详细的自定义信息
            return config;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     *
     * @param fileId      文件id
     * @param fileName    文件名称
     * @param password    密码
     * @param outformat   输出格式
     * @param dpi         pdf 转图片 设置转换结果图片的dpi
     * @param toPdf       转pdf的配置
     * @param toPng       转png的配置
     * @param etPageZoom  表格配置
     * @return 文件二进制
     * @throws Exception  抛出此异常
     */
    public abstract byte[] convert(String fileId,String fileName,String password,String outformat,Integer dpi,ToPdf toPdf,ToPng toPng,EtPageZoom etPageZoom) throws Exception;
    /**
     * 异步转换
     * @param taskId      任务id
     * @param fileId      文件id
     * @param fileName    文件名称
     * @param password    密码
     * @param outformat   输出格式
     * @param dpi         pdf 转图片 设置转换结果图片的dpi
     * @param toPdf       转pdf的配置
     * @param toPng       转png的配置
     * @param etPageZoom  表格配置
     * @return 文件二进制
     * @throws Exception  抛出此异常
     */
    public abstract FileConvertResult convert(String taskId, String fileId, String fileName, String password, String outformat, Integer dpi, ToPdf toPdf, ToPng toPng, EtPageZoom etPageZoom) throws Exception;
    /**
     * 处理回调消息
     * @param onnotifyMessage 消息数据
     */
    public abstract void handleOnnotifyMessage(OnnotifyMessage onnotifyMessage);

    /**
     * 任务查询
     */
    public abstract TaskQueryResult taskQuery(String taskId,String routeKey);
    /**
     * 文件下载
     */
    public abstract byte[] fileDowload(String dowlaodId,String routeKey);
}
